package pl.shenlon.poker.gui;

import java.awt.Color;
import java.awt.Container;
import java.awt.Image;
import java.util.Observable;
import java.util.Observer;

import javax.swing.DefaultListModel;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;

import net.miginfocom.swing.MigLayout;
import pl.shenlon.assets.Assets;
import pl.shenlon.ga.GeneticPokerPlayer;
import pl.shenlon.ga.Specimen;
import pl.shenlon.poker.cards.Hand;
import pl.shenlon.poker.game.PlayerActionType;
import pl.shenlon.poker.game.PokerPlayer;
import pl.shenlon.poker.game.RealPokerPlayer;
import pl.shenlon.poker.game.gametypes.PokerGame;

public class GameDialog extends JDialog implements Observer {

	private JList<String> gameHistoryList;

	private DefaultListModel<String> gameHistoryListModel;

	private JScrollPane gameHistoryScrollPane;

	private PlayerView playerAView, playerBView;

	private TableComponent table;

	public GameDialog() {
		super();
		initComponent();
		setModal(true);
		setSize(750, 660);
		setLocationRelativeTo(null);
	}

	public PlayerView getPlayerAView() {
		return playerAView;
	}

	public PlayerView getPlayerBView() {
		return playerBView;
	}

	public TableComponent getTable() {
		return table;
	}

	private void initComponent() {
		Container contentPane = getContentPane();
		contentPane.setLayout(new MigLayout());

		gameHistoryListModel = new DefaultListModel<String>();
		gameHistoryList = new JList<String>(gameHistoryListModel);
		gameHistoryScrollPane = new JScrollPane(gameHistoryList);
		gameHistoryScrollPane
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

		playerAView = new PlayerView();
		playerBView = new PlayerView();
		table = new TableComponent();

		contentPane.add(playerBView, "wrap");
		contentPane.add(table, "grow");
		contentPane.add(gameHistoryScrollPane, "w 200%, grow, wrap");
		contentPane.add(playerAView, "wrap");
		table.setBackground((Color) Assets.get("@colours/table"));
	}

	public void newGame(int cash, Specimen specimen, PokerGame game) {
		game.addObserver(this);
		
		GeneticPokerPlayer geneticPokerPlayer = new GeneticPokerPlayer(cash,
				specimen.copy());
		RealPokerPlayer realPokerPlayer = new RealPokerPlayer(cash);
		playGame(realPokerPlayer, geneticPokerPlayer, game, cash);
		game.deleteObserver(this);
	}

	private void playGame(PokerPlayer playerA, PokerPlayer playerB,
			PokerGame game, int cash) {
		playerA.setCash(cash);
		playerB.setCash(cash);
		game.setPot(0);
		game.setBetSize(game.getSmallBlind());
		game.clearPlayersBets();
		gameHistoryListModel.clear();
		gameHistoryListModel.addElement("Wnosisz małą w ciemno $"
				+ game.getSmallBlind());
		gameHistoryListModel.addElement("Przeciwnik wnosi dużą w ciemno $"
				+ game.getBigBlind());
		game.setPlayerA(playerA);
		game.setPlayerB(playerB);
		game.dealCards();
		setPlayerA(playerA);
		setPlayerB(playerB);
		getPlayerAView().setPlayerImage((Image) Assets.get("@players/-1"));
		setTableCards(game.getTableCards());
		setModal(false);
		setVisible(true);

		PokerPlayer winner = game.playGame(false);
		playerB.getHand().show();
		game.getTableCards().show();
		if (winner.equals(playerA)) {
			playerA.updateWins(1);
			playerB.updateLoses(1);
			gameHistoryListModel.addElement(String.format(
					(String) Assets.get("@game_messages/player_win"),
					game.getPlayerBTotalBets()));
			int option = JOptionPane.showConfirmDialog(this,
					"Wygrałeś. Czy chcesz rozegrać jeszcze jedną partię?",
					"Potwierdzenie", JOptionPane.YES_NO_OPTION,
					JOptionPane.QUESTION_MESSAGE);
			if (option == JOptionPane.YES_OPTION) {
				playGame(playerA, playerB, game, cash);
			} else {
				setVisible(false);
			}
		} else {
			playerB.updateWins(1);
			playerA.updateLoses(1);
			gameHistoryListModel.addElement(String.format(
					(String) Assets.get("@game_messages/player_lose"),
					game.getPlayerATotalBets()));
			int option = JOptionPane.showConfirmDialog(this,
					"Przegrałeś. Czy chcesz rozegrać jeszcze jedną partię?",
					"Potwierdzenie", JOptionPane.YES_NO_OPTION,
					JOptionPane.QUESTION_MESSAGE);
			if (option == JOptionPane.YES_OPTION) {
				playGame(playerA, playerB, game, cash);
			} else {
				setVisible(false);
			}
		}

	}

	public void setPlayerA(PokerPlayer player) {
		player.getHand().show();
		playerAView.setPokerPlayer(player);
		table.setPlayerAHand(player.getHand());
	}

	public void setPlayerAView(PlayerView playerAView) {
		this.playerAView = playerAView;
	}

	public void setPlayerB(PokerPlayer player) {
		playerBView.setPokerPlayer(player);
		table.setPlayerBHand(player.getHand());
	}

	public void setPlayerBView(PlayerView playerBView) {
		this.playerBView = playerBView;
	}

	public void setTable(TableComponent table) {
		this.table = table;
	}

	public void setTableCards(Hand hand) {
		table.setTableCards(hand);
	}

	@Override
	public void update(Observable o, Object arg) {
		String argument = (String) arg;
		System.out.println(argument);
		PlayerActionType type = PlayerActionType.valueOf(argument
				.substring(argument.indexOf(' ') + 1));
		String message = null;
		PokerGame game = (PokerGame) o;
		table.setPotCash(game.getPot());
		table.setBetCash(game.getBetSize());
		if (argument.startsWith("A")) {
			switch (type) {
				case FOLD :
					message = (String) Assets.get("@game_messages/player_fold");
					break;
				case RAISE :
					message = String.format(
							(String) Assets.get("@game_messages/player_raise"),
							game.getBetSize());
					break;
				case CALL :
					message = String.format(
							(String) Assets.get("@game_messages/player_call"),
							game.getBetSize());
					break;
				case CHECK :
					message = (String) Assets
							.get("@game_messages/player_check");
					break;
			}
		} else if (argument.startsWith("B")) {
			switch (type) {
				case FOLD :
					message = (String) Assets
							.get("@game_messages/opponent_fold");
					break;
				case RAISE :
					message = String.format((String) Assets
							.get("@game_messages/opponent_raise"), game
							.getBetSize());
					break;
				case BLUFF :
				case CALL :
					message = String
							.format((String) Assets
									.get("@game_messages/opponent_call"), game
									.getBetSize());
					break;
				case CHECK :
					message = (String) Assets
							.get("@game_messages/opponent_check");
					break;
			}
		}
		gameHistoryListModel.addElement(message);
		gameHistoryList.setSelectedIndex(gameHistoryListModel.getSize() - 1);
	}

	// TODO: tłumaczenie
}